﻿#region Copyright (c) 2010-2011 SFJoy .All rights reserved
//******************************************************   
//* Copyright (c) 2010-2011 SFJoy .All rights reserved
//* FileName:		MD5.cs
//* CLR version: 2.0.50727.3615
//* Author: 			SFJoy
//* Version:		 	1.0.0
//* Date:        2010-12-24 17:19:06"
//* Description:	
//*
//* History:			
//*******************************************************
#endregion Copyright (c) 2010-2011 Yeepay .All rights reserved
using System;
using System.Collections.Generic;
using System.Text;
using System.Security.Cryptography;
using System.IO;
using System.Globalization;
using System.Reflection;

namespace WZ.Common
{
    public sealed class EncryptUtils
    {

        #region Base64加密解密
        /// <summary>
        /// Base64加密
        /// </summary>
        /// <param name="input">需要加密的字符串</param>
        /// <returns></returns>
        public static string Base64Encrypt(string input)
        {
            return Base64Encrypt(input, new UTF8Encoding());
        }

        /// <summary>
        /// Base64加密
        /// </summary>
        /// <param name="input">需要加密的字符串</param>
        /// <param name="encode">字符编码</param>
        /// <returns></returns>
        public static string Base64Encrypt(string input, Encoding encode)
        {
            return Convert.ToBase64String(encode.GetBytes(input));
        }

        /// <summary>
        /// Base64解密
        /// </summary>
        /// <param name="input">需要解密的字符串</param>
        /// <returns></returns>
        public static string Base64Decrypt(string input)
        {
            return Base64Decrypt(input, new UTF8Encoding());
        }

        /// <summary>
        /// Base64解密
        /// </summary>
        /// <param name="input">需要解密的字符串</param>
        /// <param name="encode">字符的编码</param>
        /// <returns></returns>
        public static string Base64Decrypt(string input, Encoding encode)
        {
            return encode.GetString(Convert.FromBase64String(input));
        }
        #endregion

        #region MD5加密
        /// <summary>
        /// MD5加密
        /// </summary>
        /// <param name="input">需要加密的字符串</param>
        /// <returns></returns>
        public static string MD5Encrypt(string input)
        {
            return MD5Encrypt(input, new UTF8Encoding());
        }

        /// <summary>
        /// MD5加密
        /// </summary>
        /// <param name="input">需要加密的字符串</param>
        /// <param name="encode">字符的编码</param>
        /// <returns></returns>
        public static string MD5Encrypt(string input, Encoding encode)
        {
            MD5 md5 = new MD5CryptoServiceProvider();
            byte[] t = md5.ComputeHash(encode.GetBytes(input));
            StringBuilder sb = new StringBuilder(32);
            for (int i = 0; i < t.Length; i++)
                sb.Append(t[i].ToString("x").PadLeft(2, '0'));
            return sb.ToString();
        }

        /// <summary>
        /// MD5对文件流加密
        /// </summary>
        /// <param name="sr"></param>
        /// <returns></returns>
        public static string MD5Encrypt(Stream stream)
        {
            MD5 md5serv = MD5CryptoServiceProvider.Create();
            byte[] buffer = md5serv.ComputeHash(stream);
            StringBuilder sb = new StringBuilder();
            foreach (byte var in buffer)
                sb.Append(var.ToString("x2"));
            return sb.ToString();
        }
        public static string MD5Encrypt(byte[] buffer)
        {
            MD5 md5serv = MD5CryptoServiceProvider.Create();
            byte[] md5Buffer = md5serv.ComputeHash(buffer);
            StringBuilder sb = new StringBuilder();
            foreach (byte var in md5Buffer)
                sb.Append(var.ToString("x2"));
            return sb.ToString();
        }
        /// <summary>
        /// MD5加密(返回16位加密串)
        /// </summary>
        /// <param name="input"></param>
        /// <param name="encode"></param>
        /// <returns></returns>
        public static string MD5Encrypt16(string input, Encoding encode)
        {
            MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider();
            string result = BitConverter.ToString(md5.ComputeHash(encode.GetBytes(input)), 4, 8);
            result = result.Replace("-", "");
            return result;
        }
        #endregion


        #region RSA

        //public static byte[] EncryptRSA(string publicKeyAsPem, string payload, string passphrase = null)
        //{
        //    var encoder = new UTF8Encoding();
        //    byte[] byte_payload = encoder.GetBytes(payload);
        //    CryptoKey d = CryptoKey.FromPublicKey(publicKeyAsPem, passphrase);
        //    OpenSSL.Crypto.RSA rsa = d.GetRSA();
        //    byte[] result = rsa.PublicEncrypt(byte_payload, OpenSSL.Crypto.RSA.Padding.PKCS1);
        //    rsa.Dispose();
        //    return result;
        //}
        //public static string DecryptRSA(string privateKeyAsPem, byte[] payload, string passphrase = null)
        //{
        //    var encoder = new UTF8Encoding();
        //    byte[] byte_payload = payload;
        //    CryptoKey d = CryptoKey.FromPrivateKey(privateKeyAsPem, passphrase);
        //    OpenSSL.Crypto.RSA rsa = d.GetRSA();
        //    byte[] result = rsa.PrivateDecrypt(byte_payload, OpenSSL.Crypto.RSA.Padding.PKCS1);
        //    rsa.Dispose();
        //    return encoder.GetString(result);
        //}

        #endregion

        #region 3DES

        public static string EncryptTripleDES(string phrase, string key, bool hashKey = true)
        {
            var keyArray = HexStringToByteArray(hashKey ? MD5Encrypt(key) : key);
            var toEncryptArray = Encoding.UTF8.GetBytes(phrase);

            var tdes = new TripleDESCryptoServiceProvider
            {
                Key = keyArray,
                Mode = CipherMode.ECB,
                Padding = PaddingMode.PKCS7
            };

            var cTransform = tdes.CreateEncryptor();
            var resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);

            tdes.Clear();
            return ByteArrayToHexString(resultArray);
        }

        public static string DecryptTripleDES(string hash, string key, bool hashKey = true)
        {
            var keyArray = HexStringToByteArray(hashKey ? MD5Encrypt(key) : key);
            var toEncryptArray = HexStringToByteArray(hash);

            var tdes = new TripleDESCryptoServiceProvider
            {
                Key = keyArray,
                Mode = CipherMode.ECB,
                Padding = PaddingMode.PKCS7
            };

            var cTransform = tdes.CreateDecryptor();
            var resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);

            tdes.Clear();
            return Encoding.UTF8.GetString(resultArray);
        }

        #endregion

        #region Helpers

        internal static string ByteArrayToHexString(byte[] inputArray)
        {
            if (inputArray == null)
                return null;
            var o = new StringBuilder("");
            for (var i = 0; i < inputArray.Length; i++)
                o.Append(inputArray[i].ToString("X2"));
            return o.ToString();
        }

        internal static byte[] HexStringToByteArray(string inputString)
        {
            if (inputString == null)
                return null;

            if (inputString.Length == 0)
                return new byte[0];

            if (inputString.Length % 2 != 0)
                throw new Exception("Hex strings have an even number of characters and you have got an odd number of characters!");

            var num = inputString.Length / 2;
            var bytes = new byte[num];
            for (var i = 0; i < num; i++)
            {
                var x = inputString.Substring(i * 2, 2);
                try
                {
                    bytes[i] = Convert.ToByte(x, 16);
                }
                catch (Exception ex)
                {
                    throw new Exception("Part of your \"hex\" string contains a non-hex value.", ex);
                }
            }
            return bytes;
        }

        #endregion

        
    }
}
